package com.bood.shimmer.shiro;

import com.bood.shimmer.common.filter.JwtFilter;
import org.apache.shiro.authc.pam.AuthenticationStrategy;
import org.apache.shiro.authc.pam.FirstSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * <p>
 * 自定义 Shiro 配置
 * </p>
 *
 * @author：bood
 * @date：2020/9/25
 */
@Configuration
public class ShiroConfig {

    /**
     * <p>
     * SecurityManager,安全管理器,所有与安全相关的操作都会与之进行交互;
     * 它管理着所有 Subject,所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManager
     * DefaultWebSecurityManager :
     * 会创建默认的 DefaultSubjectDAO (它又会默认创建 DefaultSessionStorageEvaluator)
     * 会默认创建 DefaultWebSubjectFactory
     * 会默认创建 ModularRealmAuthenticator
     * </p>
     *
     * @param myShiroRealm: 自定义 Shiro Realm
     * @return：org.apache.shiro.web.mgt.DefaultWebSecurityManager
     * @author：bood
     * @date：2020/9/25
     */
    @Bean
    public DefaultWebSecurityManager securityManager(MyShiroRealm myShiroRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(myShiroRealm);
        // 设置 realm
        securityManager.setRealm(myShiroRealm);
        // 关闭 shiro 自带 session
        DefaultSubjectDAO subjectDAO = (DefaultSubjectDAO) securityManager.getSubjectDAO();
        ModularRealmAuthenticator realmAuthenticator = new ModularRealmAuthenticator();
        AuthenticationStrategy strategy = new FirstSuccessfulStrategy();
        realmAuthenticator.setAuthenticationStrategy(strategy);
        DefaultSessionStorageEvaluator evaluator = (DefaultSessionStorageEvaluator) subjectDAO.getSessionStorageEvaluator();
        evaluator.setSessionStorageEnabled(Boolean.FALSE);
        subjectDAO.setSessionStorageEvaluator(evaluator);
        return securityManager;
    }

    /**
     * <p>
     * 配置 Shiro 的访问策略
     * </p>
     *
     * @param securityManager: 默认的安全管理器及认证
     * @return：org.apache.shiro.spring.web.ShiroFilterFactoryBean
     * @author：bood
     * @date：2020/9/25
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 添加自己的过滤器并且取名为 jwt
        LinkedHashMap<String, Filter> filterMap = new LinkedHashMap<>(2);
        filterMap.put("jwt", new JwtFilter());
        shiroFilterFactoryBean.setFilters(filterMap);

        // 拦截器, 配置不会被拦截的链接（顺序判断）
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(2);

        // 所有匿名用户均可访问到 Controller 层的该方法下
        // swagger
        filterChainDefinitionMap.put("/doc.html", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
        filterChainDefinitionMap.put("/v2/**", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        // druid
        filterChainDefinitionMap.put("/druid/**", "anon");

        // 自定义接口放行
        filterChainDefinitionMap.put("/common/**", "anon");
        filterChainDefinitionMap.put("/demo/test/**", "anon");



        // 过滤链定义，从上向下顺序执行，一般将放在最为下边
        filterChainDefinitionMap.put("/**", "jwt");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

}